package com.wiiss.quartz.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.wiiss.common.exception.BaseException;
import com.wiiss.common.exception.ExceptionInfo;
import com.wiiss.common.utils.DateUtils;
import com.wiiss.common.utils.StringUtils;
import com.wiiss.common.utils.XMLUtils;
import com.wiiss.common.utils.file.FileUtils;
import com.wiiss.quartz.domain.SysJob;
import com.wiiss.quartz.service.ICleanService;
import com.wiiss.quartz.service.ISysJobService;
import com.wiiss.system.domain.SysConfig;
import com.wiiss.system.service.ISysConfigService;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.activiti.engine.RuntimeService;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.SAXReader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StopWatch;

import java.io.File;
import java.io.InputStream;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

@Slf4j
@Service
public class CleanServiceImpl implements ICleanService {

    @Autowired
    ISysConfigService sysConfigService;
    @Autowired
    ISysJobService sysJobService;
    @Autowired
    RuntimeService runtimeService;

    /**
     * 查询
     */
    @Override
    public JSONObject selectClean() {
        JSONObject result = new JSONObject();
        // 任务开始时间
        SysJob qSysJob = new SysJob();
        qSysJob.setInvokeTarget("cleanServiceImpl.cleanLog");
        SysJob sysJob = sysJobService.selectJobList(qSysJob).get(0);
        String startTime = null; //yyyy-MM-dd HH:mm:ss
        // 0 25 11 * * ?
        String cronExpression = sysJob.getCronExpression();
        String[] cronArr = cronExpression.split(" ");
        String cronStr = cronArr[2] + ":" + cronArr[1] + ":" + cronArr[0];
        try {
            // 这里主要取时分秒，所以设置了随便一个日期
            Date cronDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2011-07-09 " + cronStr);
            startTime = DateUtils.getStandardTime(cronDate).split(" ")[1];
        } catch (ParseException e) {
            log.error("selectClean error", e);
        }
        String taskInterval = sysConfigService.selectConfigByKey("clean.task.interval");
        if (StringUtils.isEmpty(taskInterval)) {
            throw new BaseException(ExceptionInfo.ERROR.getCode(), "未找到任务天数");
        }
        String logInterval = sysConfigService.selectConfigByKey("clean.log.interval");
        if (StringUtils.isEmpty(logInterval)) {
            throw new BaseException(ExceptionInfo.ERROR.getCode(), "未找到日志天数");
        }
        result.put("taskInterval", taskInterval);
        result.put("logInterval", logInterval);
        result.put("startTime", startTime);
        return result;
    }

    /**
     * 更新
     *
     * @param jsonObject
     */
    @Override
    public int updateClean(JSONObject jsonObject) {
        String taskInterval = jsonObject.getString("taskInterval");
        String logInterval = jsonObject.getString("logInterval");
        SysConfig taskConfig = new SysConfig();
        taskConfig.setConfigKey("clean.task.interval");
        taskConfig = sysConfigService.selectConfigList(taskConfig).get(0);
        taskConfig.setConfigValue(taskInterval);
        sysConfigService.updateConfig(taskConfig);

        SysConfig logConfig = new SysConfig();
        logConfig.setConfigKey("clean.log.interval");
        logConfig = sysConfigService.selectConfigList(logConfig).get(0);
        logConfig.setConfigValue(logInterval);
        sysConfigService.updateConfig(logConfig);

        return 0;
    }

    /**
     * 清理过期日志
     */
    @Override
    public void cleanLog() {
        log.info("开启清理过期日志文件");

        // 删除几天前的任务
        String interval = sysConfigService.selectConfigByKey("clean.log.interval");
        if (StringUtils.isEmpty(interval)) {
            throw new BaseException("未找到天数");
        }

        Date preDate = DateUtils.getPreDate(Integer.parseInt(interval));
        log.info("删除" + DateUtils.getStandardTime(preDate) + "前的日志文件");

        InputStream is = this.getClass().getResourceAsStream("/logback.xml");
        Document document = null;
        try {
            document = new SAXReader().read(is);
        } catch (DocumentException e) {
            log.error("cleanLog error", e);
        }
        String logPath = XMLUtils.getValueByName(document, "log.path");
        log.info("日志文件路径:" + logPath);
        List<File> allFile = FileUtils.getAllFile(logPath);
        for (File file : allFile) {
            String fileName = file.getName();
            String fileTime = fileName.split("\\.")[1];
            if (DateUtils.isValidDate(fileTime)) {
                // 类似这样有日期的 wiiss-f1-info.2022-05-17.log
                Date fileDate = DateUtils.dateTime(DateUtils.YYYY_MM_DD, fileTime);
                if (fileDate.before(preDate)) {
                    log.info("删除日志文件：" + file.getName());
                    FileUtils.deleteFile(file.getPath());
                }
            }
        }
        log.info("清理过期日志文件完成");
    }

    //重命名文件
    public static void reNameFile(String oldPath, String newPath) {
        boolean result = new File(oldPath).renameTo(new File(newPath));
    }

    private String prettyPrintBySecond(StopWatch stopWatch) {
        StopWatch.TaskInfo[] taskInfos = stopWatch.getTaskInfo();
        StringBuilder sb = new StringBuilder();
        sb.append('\n');
        sb.append("StopWatch '").append(stopWatch.getId()).append("': running time = ").append(stopWatch.getTotalTimeSeconds()).append(" s");
        sb.append('\n');
        if (taskInfos.length < 1) {
            sb.append("No task info kept");
        } else {
            sb.append("---------------------------------------------\n");
            sb.append("s         %     Task name\n");
            sb.append("---------------------------------------------\n");
            NumberFormat nf = NumberFormat.getNumberInstance();
            nf.setMinimumFractionDigits(3);
            nf.setGroupingUsed(false);
            NumberFormat pf = NumberFormat.getPercentInstance();
            pf.setMinimumIntegerDigits(2);
            pf.setMinimumFractionDigits(2);
            pf.setGroupingUsed(false);
            for (StopWatch.TaskInfo task : taskInfos) {
                sb.append(nf.format(task.getTimeSeconds())).append("  ");
                sb.append(pf.format((double) task.getTimeNanos() / stopWatch.getTotalTimeNanos())).append("  ");
                sb.append(task.getTaskName()).append("\n");
            }
        }
        return sb.toString();
    }
}
